/*
 * Created by SharpDevelop.
 * User: phtrung
 * Date: 8/6/2008
 * Time: 5:59 PM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.IO;
using System.Drawing;
using System.Drawing.Text;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Collections;
using System.Security.Cryptography;


namespace popLib
{
	/// <summary>
	/// Description of MyClass.
	/// </summary>
	public class ImageLib
	{
		/// <summary>
		/// Resize image by percentage of orginal size
		/// </summary>
		/// <param name="img"></param>
		/// <param name="percentage">from 1 to 100, if <1 mean 1, > 100 mean 100</1></param>
		/// <returns></returns>
		public static Image Resize(Image img, int percentage){
			int resizedW = (int)(img.Width * percentage);
    		int resizedH = (int)(img.Height * percentage);
    		return Resize(img, resizedW, resizedH);
		}
		
		/// <summary>
		/// Resize image
		/// </summary>
		/// <param name="img"></param>
		/// <param name="newSize">if width/height<=0 mean original width/height</param>
		/// <returns></returns>
		public static Image Resize(Image img, Size newSize){
			return Resize( img, newSize.Width, newSize.Height );
		}
		
		/// <summary>
		/// Resize image
		/// </summary>
		/// <param name="img"></param>
		/// <param name="resizedW">if <=0 mean original width</param>
		/// <param name="resizedH">if <=0 mean original height</param>
		/// <returns></returns>
		public static Image Resize(Image img, int resizedW, int resizedH)
		{	
			resizedW = resizedW <= 0 ? img.Width : resizedW;
			resizedH = resizedH <= 0 ? img.Height : resizedH;
			
		    Bitmap bmp = new Bitmap(resizedW, resizedH);
		    Graphics graphic = Graphics.FromImage((Image)bmp);
		    
		    graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
		    graphic.SmoothingMode = SmoothingMode.HighQuality;
			graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
			graphic.CompositingQuality = CompositingQuality.HighQuality;
			
		    graphic.DrawImage(img, 0, 0, resizedW, resizedH);
		    graphic.Dispose();
		    return (Image)bmp;
		}
			
		public static Size GetImageSizeFromFile(string imgFile){
			Image img = Image.FromFile(imgFile);
			return img.Size;
		}
		
		/// <summary>
		/// Load image and resize and save to destination file
		/// </summary>
		/// <param name="imgSrc"></param>
		/// <param name="imgDes">if imgDes is null or blank mean save to imgSrc</param>
		/// <param name="size">if width/height<=0 mean original width/height</param>
		public static void ResizeImageFile( string imgSrc, string imgDes, Size size ){						
			Image img = Image.FromFile(imgSrc);
			
			size = new Size( size.Width <= 0 ? img.Width : size.Width, size.Height <= 0 ? img.Height : size.Height );
			img = Resize( img, size );
						
			ImageFormat format = ImageFormat.Png;
			if(imgDes.IndexOf(".gif") >=0 ) format = ImageFormat.Gif;
			if(imgDes.IndexOf(".jpg") >=0 ) format = ImageFormat.Jpeg;
					
			if(!StringLib.isValid(imgDes)) imgDes = imgSrc;
			
			img.Save(imgDes, format);
			img.Dispose();
		}
		
		public static Bitmap ResizePadding(Bitmap bitmap, Padding region, Size size){
	        						
	        //L15, R15, T32, B19
	        Bitmap MyBitmap = new Bitmap(size.Width, size.Height, PixelFormat.Format32bppArgb);
	        Graphics Gr = Graphics.FromImage(MyBitmap);
	        
			Rectangle DestLU = new Rectangle(0, 0, region.Left, region.Top);
			Rectangle DestLM = new Rectangle(0, region.Top, region.Left, size.Height - (region.Top+region.Bottom));
			Rectangle DestLD = new Rectangle(0, size.Height - region.Bottom, region.Left, region.Bottom);
			Rectangle DestMU = new Rectangle(region.Left, 0, size.Width - (region.Left+region.Right), region.Top);
			Rectangle DestMM = new Rectangle(region.Left, region.Top, size.Width - (region.Left+region.Right), size.Height - (region.Top+region.Bottom));
			Rectangle DestMD = new Rectangle(region.Left, size.Height - region.Bottom, size.Width - (region.Left+region.Right), region.Bottom);
			Rectangle DestRU = new Rectangle(size.Width - region.Right, 0, region.Right, region.Top);
			Rectangle DestRM = new Rectangle(size.Width - region.Right, region.Top, region.Right, size.Height - (region.Top+region.Bottom));
			Rectangle DestRD = new Rectangle(size.Width - region.Right, size.Height - region.Bottom, region.Right, region.Bottom);
	        		
	        Rectangle SourceLU = new Rectangle(0, 0, region.Left, region.Top);
	        Rectangle SourceLM = new Rectangle(0, region.Top, region.Left, bitmap.Height - (region.Top+region.Bottom));
	        Rectangle SourceLD = new Rectangle(0, bitmap.Height - region.Bottom, region.Left, region.Bottom);
	        Rectangle SourceMU = new Rectangle(region.Left, 0, bitmap.Width - (region.Left+region.Right), region.Top);
	        Rectangle SourceMM = new Rectangle(region.Left, region.Top, bitmap.Width - (region.Left+region.Right), bitmap.Height - (region.Top+region.Bottom));
	        Rectangle SourceMD = new Rectangle(region.Left, bitmap.Height - region.Bottom, bitmap.Width - (region.Left+region.Right), region.Bottom);
	        Rectangle SourceRU = new Rectangle(bitmap.Width - region.Right, 0, region.Right, region.Top);
	        Rectangle SourceRM = new Rectangle(bitmap.Width - region.Right, region.Top, region.Right, bitmap.Height - (region.Top+region.Bottom));
	        Rectangle SourceRD = new Rectangle(bitmap.Width - region.Right, bitmap.Height - region.Bottom, region.Right, region.Bottom);
	        
	        Gr.DrawImage(bitmap, DestLU, SourceLU, GraphicsUnit.Pixel);
	        Gr.DrawImage(bitmap, DestLM, SourceLM, GraphicsUnit.Pixel);
	        Gr.DrawImage(bitmap, DestLD, SourceLD, GraphicsUnit.Pixel);
	        Gr.DrawImage(bitmap, DestMU, SourceMU, GraphicsUnit.Pixel);
	        Gr.DrawImage(bitmap, DestMM, SourceMM, GraphicsUnit.Pixel);
	        Gr.DrawImage(bitmap, DestMD, SourceMD, GraphicsUnit.Pixel);
	        Gr.DrawImage(bitmap, DestRU, SourceRU, GraphicsUnit.Pixel);
	        Gr.DrawImage(bitmap, DestRM, SourceRM, GraphicsUnit.Pixel);
	        Gr.DrawImage(bitmap, DestRD, SourceRD, GraphicsUnit.Pixel);
	        
	        Gr.Dispose();
	        return MyBitmap;
		}
		
		public static Image CreateThumbnailImage( Image img, int width, int height )
		{
			int nwidth  = (height * img.Width) / img.Height;
			int nheight = (width * img.Height) / img.Width ;
			
			if( width <= 0 )
				return Resize( img, nwidth, height );
			else if( height <= 0 )
				return Resize( img, width, nheight );
			else if( nwidth > width )
				return Resize( img, width, nheight );
			else 
				return Resize( img, nwidth, height );
			
			
		}
		
		public static Image ChangeImageOpacity( Image img, float opacity ){
			Image result 		= new Bitmap(img.Width, img.Height);
			Graphics painter 	= Graphics.FromImage(result);
			
			ColorMatrix cm 		= new ColorMatrix();
			cm.Matrix33 		= opacity;
			ImageAttributes ia 	= new ImageAttributes();
			ia.SetColorMatrix(cm);
			
			painter.DrawImage(img, new Rectangle(0,0,img.Width,img.Height),
    			0,0,img.Width, img.Height, GraphicsUnit.Pixel, ia);
			
			return result;
		}
		
		public static Image CropImage( Image img, int x, int y, int nWidth, int nHeight )
		{
			Image result = new Bitmap( nWidth, nHeight);
			using( Graphics g = Graphics.FromImage( result ) )				
				g.DrawImage(img, new Rectangle(0, 0, nWidth, nHeight), x, y, nWidth, nHeight, GraphicsUnit.Pixel);
				
			return (Image)result;
		}
		
		public enum CompareResult
        {
            ciCompareOk,
            ciPixelMismatch,
            ciSizeMismatch
        };

		public static CompareResult CompareImageSize(Bitmap bmp1, Bitmap bmp2){
			CompareResult cr = CompareResult.ciCompareOk;
            if (bmp1.Size != bmp2.Size)
            {
                cr = CompareResult.ciSizeMismatch;
            }
            return cr;
		}
		
        public static CompareResult CompareImageByte(Bitmap bmp1, Bitmap bmp2)
        {
        	CompareResult cr = CompareImageSize(bmp1, bmp2);
        	
        	if(cr == CompareResult.ciCompareOk){
                //Convert each image to a byte array

                System.Drawing.ImageConverter ic = 
                       new System.Drawing.ImageConverter();
                byte[] btImage1 = new byte[1];
                btImage1 = (byte[])ic.ConvertTo(bmp1, btImage1.GetType());
                byte[] btImage2 = new byte[1];
                btImage2 = (byte[])ic.ConvertTo(bmp2, btImage2.GetType());
                
                //Compute a hash for each image

                SHA256Managed shaM = new SHA256Managed();
                byte[] hash1 = shaM.ComputeHash(btImage1);
                byte[] hash2 = shaM.ComputeHash(btImage2);

                //Compare the hash values

                for (int i = 0; i < hash1.Length && i < hash2.Length 
                                  && cr == CompareResult.ciCompareOk; i++)
                {
                    if (hash1[i] != hash2[i])
                        cr = CompareResult.ciPixelMismatch;
                }
            }
            return cr;
        }
        
        public static CompareResult CompareImagePixel(Bitmap bmp1, Bitmap bmp2){
        	CompareResult cr = CompareImageSize(bmp1, bmp2);
        	
        	if(cr == CompareResult.ciCompareOk)
        	{
            	for(int i=0; i<bmp1.Width; i++){
            		for(int j=0; j<bmp1.Height; j++){
            			if( bmp1.GetPixel(i,j) != bmp2.GetPixel(i,j) ){
            				cr = CompareResult.ciPixelMismatch;
            				break;
            			}
            		}
            	}
            }
            
            return cr;
        }
        
        public static CompareResult CompareImageStream(string file1, string file2){
        	CompareResult cr = CompareResult.ciCompareOk;
        	using (StreamReader str1 = new StreamReader(file1))
            {
                using (StreamReader str2 = new StreamReader(file2))
                {
                    if (str1.ReadToEnd() != str2.ReadToEnd())
                    {
                        cr = CompareResult.ciPixelMismatch;
                    }
                }
            }
            return cr;
        }
        
        public static CompareResult CompareImageStream(Bitmap bmp1, Bitmap bmp2){
        	CompareResult cr = CompareImageSize(bmp1, bmp2);
        	if( cr == CompareResult.ciCompareOk ){        	
	        	string file1 = Path.GetTempFileName();
	        	string file2 = Path.GetTempFileName();
	        	
	        	bmp1.Save(file1, ImageFormat.Png);
	        	bmp2.Save(file2, ImageFormat.Png);
	        	
	        	cr = CompareImageStream(file1, file2);
	        	File.Delete(file1);
	        	File.Delete(file2);
	        	
	        	GC.Collect();
        	}        	
        	return cr;
        }


        public static string ToBase64(Image image, ImageFormat format)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                // Convert Image to byte[]
                image.Save(ms, format);
                byte[] imageBytes = ms.ToArray();

                // Convert byte[] to Base64 String
                string base64String = Convert.ToBase64String(imageBytes);
                return base64String;
            }
        }

        public static Image FromBase64(string base64String)
        {
            // Convert Base64 String to byte[]
            byte[] imageBytes = Convert.FromBase64String(base64String);
            MemoryStream ms = new MemoryStream(imageBytes, 0,
              imageBytes.Length);

            // Convert byte[] to Image
            ms.Write(imageBytes, 0, imageBytes.Length);
            Image image = Image.FromStream(ms, true);
            return image;
        }
	}	
}
